package com.flyduck.vueshop.order.admin.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.flyduck.vueshop.common.core.exception.BusinessException;
import com.flyduck.vueshop.common.core.utils.BeanUtils;
import com.flyduck.vueshop.common.core.utils.StringUtils;
import com.flyduck.vueshop.order.constant.OrderConstant;
import com.flyduck.vueshop.order.admin.service.AdminOrderService;
import com.flyduck.vueshop.order.admin.vo.*;
import com.flyduck.vueshop.order.entity.AppOrder;
import com.flyduck.vueshop.order.entity.AppOrderItem;
import com.flyduck.vueshop.order.entity.AppRefund;
import com.flyduck.vueshop.order.manager.AppOrderManager;
import com.flyduck.vueshop.order.mapper.AppOrderItemMapper;
import com.flyduck.vueshop.order.mapper.AppOrderMapper;
import com.flyduck.vueshop.order.mapper.AppRefundMapper;
import com.flyduck.vueshop.order.utils.KdApiSearchUtils;
import com.flyduck.vueshop.user.feign.RemoteUserFeignClient;
import com.flyduck.vueshop.user.vo.RemoteUserRespVO;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * AdminOrderServiceImpl
 * </p>
 *
 * @author flyduck
 * @since 2024-06-11
 */
@Service
public class AdminOrderServiceImpl implements AdminOrderService {

    @Resource
    private AppOrderMapper appOrderMapper;
    @Resource
    private AppOrderItemMapper appOrderItemMapper;
    @Resource
    private AppRefundMapper appRefundMapper;
    @Resource
    private AppOrderManager appOrderManager;
    @Resource
    private RemoteUserFeignClient remoteUserFeignClient;

    @Override
    public Page<AdminOrderRespVO> getOrderPage(Page page, AdminOrderQueryReqVO adminOrderQueryReqVO) {
        return appOrderMapper.getOrderPage(page, adminOrderQueryReqVO);
    }

    @Override
    public List<AdminDictRespVO> getOrderStatusList() {
        List<AdminDictRespVO> adminDictRespVOList = new ArrayList<>();
        for (OrderConstant.OrderStatus orderStatus : OrderConstant.OrderStatus.values()) {
            AdminDictRespVO adminDictRespVO = new AdminDictRespVO();
            adminDictRespVO.setKey(orderStatus.getCode());
            adminDictRespVO.setValue(orderStatus.getDescription());
            adminDictRespVOList.add(adminDictRespVO);
        }
        return adminDictRespVOList;
    }

    @Override
    public AdminOrderDetailsRespVO getOrderDetailsById(Long id) {
        //订单基本信息
        AppOrder appOrder = appOrderMapper.selectById(id);
        if(appOrder == null){
            throw new BusinessException("该订单不存在");
        }
        AdminOrderDetailsRespVO adminOrderDetailsRespVO = BeanUtils.toBean(appOrder, AdminOrderDetailsRespVO.class);

        //订单项列表
        List<AppOrderItem> appOrderItemList = appOrderItemMapper.getAppOrderItemListByOrderId(id);
        List<AdminOrderDetailsRespVO.AppOrderItemVO> appOrderItemVOList = BeanUtils.toBeanList(appOrderItemList, AdminOrderDetailsRespVO.AppOrderItemVO.class);
        adminOrderDetailsRespVO.setOrderItems(appOrderItemVOList);

        //订单用户信息
        RemoteUserRespVO remoteUserRespVO = remoteUserFeignClient.getUserById(appOrder.getUserId()).getData();
        adminOrderDetailsRespVO.setUsername(remoteUserRespVO.getUsername());
        adminOrderDetailsRespVO.setUserAvatar(remoteUserRespVO.getAvatar());

        //退款信息
        AppRefund appRefund = appRefundMapper.selectOne(
                new LambdaQueryWrapper<AppRefund>()
                        .eq(AppRefund::getOrderId, id)
        );
        AdminOrderDetailsRespVO.AppRefundVO appRefundVO = BeanUtils.toBean(appRefund, AdminOrderDetailsRespVO.AppRefundVO.class);
        adminOrderDetailsRespVO.setAppRefund(appRefundVO);
        return adminOrderDetailsRespVO;
    }

    @Override
    public void orderDelivery(AdminOrderDeliveryReqVO adminOrderDeliveryReqVO) {
        AppOrder appOrder = appOrderMapper.selectById(adminOrderDeliveryReqVO.getId());
        if (appOrder == null) {
            throw new BusinessException("该订单不存在");
        }

        if(OrderConstant.OrderStatus.PENDING_DELIVERY.getCode() != appOrder.getOrderStatus()){
            throw new BusinessException("该订单状态不允许发货");
        }

        if(StringUtils.isBlank(adminOrderDeliveryReqVO.getDeliveryCompany()) || StringUtils.isBlank(adminOrderDeliveryReqVO.getDeliverySn())){
            throw new BusinessException("参数异常");
        }

        appOrder.setDeliveryCompany(adminOrderDeliveryReqVO.getDeliveryCompany());
        appOrder.setDeliverySn(adminOrderDeliveryReqVO.getDeliverySn());
        appOrder.setDeliveryTime(LocalDateTime.now());
        appOrder.setOrderStatus(OrderConstant.OrderStatus.PENDING_RECEIPT.getCode());
        appOrder.setUpdated(LocalDateTime.now());

        //记录发货人
        appOrder.setAdminNote("管理员：" + StpUtil.getLoginIdAsLong() + "发货：" + appOrder.getAdminNote());

        appOrderMapper.updateById(appOrder);
    }

    @Override
    public List<AdminDeliveryTraceRespVO> getDeliveryTraceListById(Long id) throws Exception {
        AppOrder appOrder = appOrderMapper.selectById(id);

        String deliveryInfo = new KdApiSearchUtils().getDelivery(appOrder.getDeliveryCompany(), appOrder.getDeliverySn());

        JSONArray traces = JSONUtil.parseObj(deliveryInfo).getJSONArray("Traces");
        return traces.stream()
                .map(trace -> {
                    JSONObject jsonObject = JSONUtil.parseObj(trace);
                    AdminDeliveryTraceRespVO adminDeliveryTraceRespVO = new AdminDeliveryTraceRespVO();
                    adminDeliveryTraceRespVO.setAcceptTime(jsonObject.getStr("AcceptTime"));
                    adminDeliveryTraceRespVO.setAcceptStation(jsonObject.getStr("AcceptStation"));
                    adminDeliveryTraceRespVO.setRemark(jsonObject.getStr("Remark"));

                    return adminDeliveryTraceRespVO;
                }).collect(Collectors.toList());
    }

    @Override
    public void closeOrder(AdminOrderCloseReqVO adminOrderDeliveryReqVO) {
        appOrderManager.closeOrder(adminOrderDeliveryReqVO.getId(),adminOrderDeliveryReqVO.getAdminNote(),StpUtil.getLoginIdAsLong());
    }
}
